package indi.h.security.encryption.asym;

import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;

import javax.crypto.Cipher;

import indi.h.security.encryption.AsymCrypt;
import indi.h.security.encryption.sym.SymCryptImp;
import indi.h.security.encryption.util.KeysConvert;

public class AsymCryptImp extends SymCryptImp implements AsymCrypt {
	protected PublicKey publicKey;
	protected PrivateKey privateKey;
	protected PublicKey outPublicKey;
	protected PrivateKey outPrivateKey;

	@Override
	public void customInit() {
		try {
			byte[] puk = ((AsymCryptParameter) params).getPublicKey();
			if (puk != null)
				putUpPublicKey(puk);
			byte[] prk = ((AsymCryptParameter) params).getPrivateKey();
			if (prk != null) {
				putUpPrivateKey(prk);
			} else {
				KeyPairGenerator kpg = KeyPairGenerator.getInstance(params.getAlgorithm());
				kpg.initialize(params.getLength(), new SecureRandom(params.getPassword().getBytes(params.getCode())));
				KeyPair kp = kpg.generateKeyPair();
				publicKey = kp.getPublic();
				privateKey = kp.getPrivate();
			}
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void beforeDecrypt() {
		try {
			if (outPrivateKey != null)
				cipher.init(Cipher.DECRYPT_MODE, outPrivateKey);
			else
				cipher.init(Cipher.DECRYPT_MODE, privateKey);
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void beforeEncrypt() {
		try {
			if (outPublicKey != null)
				cipher.init(Cipher.ENCRYPT_MODE, outPublicKey);
			else
				cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
	}

	@Override
	public byte[] getPublicKey() {
		try {
			// PrivateKey p = outPrivateKey == null ? privateKey :
			// outPrivateKey;
			if (outPublicKey != null)
				return outPublicKey.getEncoded();
			return publicKey.getEncoded();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public byte[] getPrivateKey() {
		try {
			if (outPrivateKey != null)
				return outPrivateKey.getEncoded();
			return privateKey.getEncoded();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public void putUpPublicKey(byte[] b) {
		outPublicKey = KeysConvert.x509Key(b, ((AsymCryptParameter) params).getKeyFactory());
	}

	@Override
	public void putUpPrivateKey(byte[] b) {
		outPrivateKey = KeysConvert.pkcs8Key(b, ((AsymCryptParameter) params).getKeyFactory());
	}

}
